home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / cc04.arc / RDMSDOS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-03-15  |  5.6 KB  |  267 lines

  1. /*
  2.  
  3.     This program reads/writes MS-DOS formatted disks,
  4. using the CPM bios routines.  The data is converted to/from
  5. C (non-ascii) files.  The code is written so that it can
  6. be compiled with Small-C, but uses K&R standard I/O
  7. whenever possible.
  8.  
  9. Author:    Bob Alverson
  10.     8717 Empire Ct.
  11.     Cincinnati, OH  45231
  12.     513-729-1676
  13.  
  14. 1.1     9 DEC 83    Add ability to read all four IBM formats
  15. 1.0    27 NOV 83    First working version.
  16.  
  17. */
  18.  
  19.  
  20. #include <stdio.h>
  21.  
  22. /* Define the disk bios calls */
  23.  
  24. #define    SELDSK    9            /* Select disk drive */
  25. #define    SETTRK    10            /* Select track */
  26. #define    SETSEC    11            /* Select sector */
  27. #define    SETDMA    12            /* Set DMA address */
  28. #define    RDSEC    13            /* Read sector */
  29. #define    WRSEC    14            /* Write sector */
  30. #define SECTRAN    16            /* Translate sector # */
  31.  
  32. #define CURDSK    25            /* bdos selected disk */
  33.  
  34. /* disk parameters */
  35.  
  36. #define ALLMAX    1024            /* maximum alloc table size */
  37. #define DIRMAX    7*512            /* maximum directory size */
  38.  
  39. /* misc data */
  40.  
  41. #define DATSIZ    0x4000            /* size of data buffer */
  42.  
  43. /* global data */
  44.  
  45. char    spttbl[4] = {32, 32, 36, 36};    /* sectors per track (logical) */
  46. int    spt;
  47.  
  48. char    alltbl[4] = {8, 4, 8, 4};    /* size of alloc table / 128 */
  49. int    allsiz;
  50.  
  51. char    dirtbl[4] = {28, 16, 28, 16};    /* size of directory / 128 */
  52. int    dirsiz;
  53.  
  54. int    blktbl[4] = {8, 4, 8, 4};    /* size of block / 128 */
  55. int    blksiz;
  56. int    blklen;                /* block size in bytes */
  57.  
  58. int    secofs;
  59. char    allmap[ALLMAX];            /* allocation map */
  60. char    dirbuf[DIRMAX];            /* directory data */
  61. char    datbuf[DATSIZ];            /* data transfer buffer */
  62. char    *datptr;
  63. int    cpmdsk;                /* cpm default disk */
  64. char    xfile[20];            /* filename to transfer */
  65. int    drive;                /* drive of MSDOS disk */
  66. int    blk;                /* MSDOS block number */ 
  67. int    xtra, blks;            /* file length */
  68. FILE    *cfile;                /* output file stream */
  69.  
  70. main()
  71. {
  72.     fputs("\nRead MS-DOS disks, Version 1.1\nDec  9, 1983\n", stdout);
  73.     do {
  74.         fputs("Drive of MSDOS disk: ",stdout);
  75.         fgets(xfile, 20, stdin);
  76.         drive = toupper(*xfile) - 'A';
  77.         if (drive < 0 || drive >= 16) {
  78.             fputs("\n\7Drive spec error!\n", stderr);
  79.             drive = -1;        /* flag bad drive */
  80.         }
  81.     } /* do */
  82.     while (drive < 0);
  83.  
  84.     cpmdsk = bdos(CURDSK, 0);
  85.  
  86.     bios(SELDSK, drive, 0);            /* select disk drive */
  87.     dettype();
  88.  
  89.     readdsk(4, allsiz, allmap);        /* read allocation map in */
  90.     readdsk(allsiz*2+4, dirsiz, dirbuf);    /* read dir into memory */
  91.  
  92.     bios(SELDSK, cpmdsk, 1);
  93.  
  94.     while (getnam()) {
  95.         if (find()) {
  96.             cfile = fopen(xfile, "w");
  97.             bios(SELDSK, drive, 1);
  98.             datptr = datbuf;
  99.             do {
  100.                 readblk(blk, datptr);
  101.                 if (blks) {    /* complete sector */
  102.                     --blks;
  103.                     datptr += blklen;
  104.                 }
  105.                 else {        /* partial sector */
  106.                     datptr += xtra;
  107.                     xtra = 0;
  108.                 }
  109.                 if (datptr > datbuf+DATSIZ-blklen) {
  110.                     bios(SELDSK, cpmdsk, 1);
  111.                     fwrite(datbuf, 1, datptr-datbuf, cfile);
  112.                     bios(SELDSK, drive, 1);
  113.                     datptr = datbuf;
  114.                 } /* if */
  115.                 nxtblk();
  116.             } /* do */
  117.             while (blks || xtra);
  118.             bios(SELDSK, cpmdsk, 1);
  119.             fwrite(datbuf, 1, datptr-datbuf, cfile);
  120.             fclose(cfile);
  121.         } /* if */
  122.         else fputs("\nFile not found\n",stdout);
  123.     } /* while */
  124. } /* main */
  125.  
  126.  
  127. dettype()        /* determine disk type */
  128. {
  129.     char    secbuf[128];
  130.     int    dsktyp;
  131.  
  132.     readsec(0, 5, secbuf);
  133.     dsktyp = (~ *secbuf) & 3;
  134.  
  135.     spt = spttbl[dsktyp];
  136.     allsiz = alltbl[dsktyp];
  137.     dirsiz = dirtbl[dsktyp];
  138.     blksiz = blktbl[dsktyp];
  139.  
  140.     blklen = blksiz*128;
  141.     secofs = ((allsiz - blksiz) << 1) + dirsiz + 4;
  142. } /* dettype */
  143.  
  144.  
  145. getnam()
  146. {
  147.     char *str, *ptr;
  148.  
  149.     fputs("\nEnter filename: ", stdout);
  150.     str = fgets(xfile, 20, stdin);
  151.     if (ptr=strchr(xfile, '\n')) *ptr = '\0';
  152.     return str;
  153. }
  154.  
  155.  
  156. /* read MSDOS block */
  157.  
  158. readblk(blkno, bufptr)
  159. int    blkno;
  160. char    *bufptr;
  161. {
  162.     readdsk((blkno * blksiz) + secofs, blksiz, bufptr);
  163. }
  164.  
  165.  
  166. readdsk(dsksec, numsec, bufptr)
  167. int    dsksec,
  168.     numsec;
  169. char    *bufptr;
  170. {
  171.     do {
  172.         readsec(dsksec/spt, (dsksec%spt)+1, bufptr);
  173.         bufptr += 128;
  174.         ++dsksec;
  175.     } /* do */
  176.      while (--numsec);    /* do all sectors requested */
  177. } /* readdsk */
  178.  
  179.  
  180. readsec(trk, sec, buf)
  181. int    trk, sec;
  182. char    *buf;
  183. {
  184.     int retcode;
  185.  
  186.     bios(SETTRK, trk, 0);
  187.     bios(SETSEC, sec, 0);
  188.     bios(SETDMA, buf, 0);
  189.     do {
  190.         if (retcode = bios(RDSEC, 0, 0)) {
  191.             char ask[3];
  192.             fputs("\nDisk read error\nIgnore or Retry? ", stdout);
  193.             fgets(ask, 3, stdin);
  194.             if (toupper(*ask) == 'I') retcode = 0;
  195.         } /* if */
  196.     } /* do */
  197.     while (retcode);
  198. } /* readsec */
  199.  
  200.  
  201. /* find next block (cluster) in chain */
  202.  
  203. nxtblk()
  204. {
  205.     int nblk;
  206.     int *blkptr;
  207.  
  208.     blkptr = allmap + ((blk*3) >> 1);
  209.     nblk = *blkptr;
  210.     if (blk & 1) nblk >>= 4;
  211.     blk = nblk & 0x0fff;
  212. }
  213.  
  214. /* find file name in directory buffer */
  215.  
  216. find()
  217. {
  218.     char    name[12];
  219.     char    *dirptr;
  220.     int    *blkptr;
  221.  
  222.     fmtfn(xfile, name);
  223.     dirptr = dirbuf;
  224.     while (strncmp(dirptr, name, 11) && *dirptr) dirptr += 32;
  225.     if (*dirptr) {
  226.         blk = *(blkptr = dirptr+26);
  227.         xtra = *(++blkptr);
  228.         blks = (xtra/blklen) + *(++blkptr)*(512/blksiz);
  229.         xtra %= blklen;
  230.         return 1;
  231.     }
  232.     return 0;    /* not found */
  233. }
  234.  
  235. /* format filename for directory search */
  236.  
  237. fmtfn(text, buf)
  238. char    *text, *buf;
  239. {
  240.     if (text[1] == ':') text += 2;    /* skip over drive */
  241.  
  242.     fmtbit(&text, buf, 8);
  243.     fmtbit(&text, buf+8, 3);
  244.  
  245.     buf[11] = 0;
  246. }
  247.  
  248. fmtbit(tptr, dest, cnt)
  249. int    *tptr;        /* should be char **text */
  250. char    *dest;
  251. int    cnt;
  252. {
  253.     char    *text;
  254.  
  255.     text = *tptr;
  256.     while (--cnt >= 0) {
  257.         if (*text && *text != '.')
  258.             *dest = toupper(*text++);    /* no macro allowed */
  259.         else
  260.             *dest = ' ';
  261.         ++dest;
  262.     }
  263.     while (*text && *text != '.') ++text;
  264.     if (*text == '.') ++text;    /* scan past . */
  265.     *tptr = text;
  266. }
  267.